feat(gardener/daemon): add --sync-mode enum + --sync-assignee override#342
Open
serenakeyitan wants to merge 1 commit intomainfrom
Open
feat(gardener/daemon): add --sync-mode enum + --sync-assignee override#342serenakeyitan wants to merge 1 commit intomainfrom
serenakeyitan wants to merge 1 commit intomainfrom
Conversation
Closes #341. ## What `gardener start` previously exposed only `--sync-apply` (boolean), which mapped to `gardener sync --apply` on each sync-sweep. There was no way to configure the daemon to run `gardener sync --open-issues`, so the autonomous issue-first chain (source PR → tree issue → breeze → draft-node PR) required a side cron to call `sync --open-issues` periodically. This PR replaces the boolean with a three-value enum and adds an optional assignee override: --sync-mode <detect|apply|open-issues> detect Default. Run `gardener sync` only. No writes. apply Run `gardener sync --apply`. One aggregated tree PR. open-issues Run `gardener sync --open-issues`. One tree issue per drift proposal; breeze + draft-node handle each. --sync-assignee <user> Only valid with `--sync-mode open-issues`. Overrides NODE.md- resolved owners so every opened issue is assigned to this user. Intended for testing against third-party repos where you don't want to ping real domain owners. ## Back-compat `--sync-apply` is retained as a deprecated alias: - Emits a deprecation warning on use. - Maps to `--sync-mode apply`. - Mutually exclusive with `--sync-mode` (parser rejects both). - Legacy on-disk configs that still have `syncApply: true` and no `syncMode` coerce to `syncMode: "apply"` at load time. Will be removed in a future minor. ## Implementation - `engine/daemon/config.ts`: add `SyncMode` type, replace `GardenerDaemonConfig.syncApply` with `syncMode` + optional `syncAssignee`. `coerceSyncMode` handles the legacy-config path. `buildDaemonConfig` accepts either `syncMode` or the legacy `syncApply`; `syncMode` wins. Drops `syncAssignee` when mode is not open-issues so CLI-level validation isn't bypassed via the builder. - `engine/daemon/loop.ts`: `buildSyncSweepArgs` switches on `syncMode`; forwards `--assignee <user>` to the child sync process only when configured. - `engine/commands/start.ts`: extend parser with `--sync-mode`, `--sync-assignee`, deprecated `--sync-apply` handling. Validate mode/assignee/deprecation combinations with clear error messages. Update USAGE to explain all three modes. ## Acceptance criteria (from #341) - [x] `gardener start --sync-mode open-issues ...` starts the daemon and sync-sweep invokes `gardener sync --open-issues`. - [x] `gardener start --sync-mode apply ...` behaves like the old `--sync-apply`. - [x] `gardener start --sync-apply ...` still works, prints deprecation warning, maps to `--sync-mode apply`. - [x] `gardener start --sync-mode open-issues --sync-assignee alice ...` forwards `--assignee alice` to the child sync process. - [x] `gardener start --sync-mode apply --sync-assignee alice ...` rejects with a clear parser error. - [x] `gardener start --sync-apply --sync-mode apply ...` rejects with "mutually exclusive" error. - [x] Existing daemon config-persistence tests still pass. Added new tests for the enum shape + legacy coercion. - [x] Help output explains all three modes clearly. ## Tests 15 new unit tests in `tests/gardener/gardener-daemon.test.ts`: - config round-trip for detect / apply / open-issues modes - syncAssignee persisted in open-issues, dropped in other modes - legacy `syncApply: true` on-disk config coerces to `syncMode: "apply"` - buildSyncSweepArgs for each mode, with/without assignee - CLI parser: accept, reject invalid mode, reject assignee outside open-issues, reject sync-apply + sync-mode mutex, deprecation warning on sync-apply All 47 tests in `gardener-daemon.test.ts` pass; the file grew from 32 to 47 tests. ## E2E Six scenarios exercised end-to-end against the built CLI (not just unit tests), required by #341: 1. `--sync-mode open-issues --sync-assignee serenakeyitan --dry-run` → preview shows `sync-mode: open-issues`, `sync-assignee: serenakeyitan`; no config.json written (dry-run honored). 2. `--sync-apply --dry-run` → deprecation warning printed, config preview shows `sync-mode: apply`. 3. `--sync-mode garbage --dry-run` → exit=1, clear error naming accepted values. 4. `--sync-mode apply --sync-assignee alice --dry-run` → exit=1, clear error citing mode. 5. `--sync-apply --sync-mode apply --dry-run` → exit=1, "mutually exclusive". 6. Real daemon boot (no dry-run) with `--sync-mode open-issues --sync-assignee serenakeyitan` → config.json on disk has `syncMode: "open-issues"` and `syncAssignee: "serenakeyitan"`; daemon stops cleanly. ## Env - Built against first-tree main @ a03a852 (v0.3.2 release). - Typecheck clean; build clean; full unit suite green (1215 passed, 51 skipped).
Contributor
Author
|
@bingran-you friendly ping — could you take a look when you have a moment? This closes #341 (the daemon |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #341.
Summary
--sync-applywith--sync-mode <detect|apply|open-issues>.open-issueslets the daemon periodically rungardener sync --open-issues, closing the autonomous issue-first chain that previously required a side cron.--sync-assignee USERoverride, valid only with--sync-mode open-issues. Forwards to the child sync process's--assigneeflag so testing against third-party repos doesn't spam real NODE.md owners.--sync-applyas a deprecated alias (warns + maps to--sync-mode apply; mutex with--sync-mode). Legacy on-disk configs withsyncApply: truecoerce at load time.Implementation
4 files, ~370 lines (most of that is tests):
engine/daemon/config.ts—SyncModetype,coerceSyncModewith legacy fallback, dropsyncAssigneeoutside open-issues mode.engine/daemon/loop.ts—buildSyncSweepArgsswitches on mode, forwards--assignee.engine/commands/start.ts— parse--sync-mode/--sync-assignee, validate combinations, emit deprecation warning, update USAGE.tests/gardener/gardener-daemon.test.ts— 15 new unit tests covering config round-trip, legacy coercion, arg builder per mode, CLI parser happy + error paths.Acceptance criteria (from #341)
All 7 checked off in the commit body. Key ones:
--sync-mode open-issuesdaemon sync-sweep invokesgardener sync --open-issues.--sync-mode applypreserves old--sync-applybehavior.--sync-applystill works, prints warning, maps to apply.--sync-assigneeforwards to child sync--assigneein open-issues mode only.--sync-assigneein non-open-issues modes → parser error.--sync-apply+--sync-modetogether → parser error.E2E tests (required by #341)
Six scenarios exercised against the built CLI (not just unit tests):
--sync-mode open-issues --sync-assignee serenakeyitan --dry-run→ preview matches; dry-run honored (no config written).--sync-apply --dry-run→ warning printed, maps to apply.--sync-mode garbage→ exit=1, clear error naming accepted values.--sync-mode apply --sync-assignee alice→ exit=1, cites mode.--sync-apply --sync-mode apply→ exit=1, "mutually exclusive".--sync-mode open-issues --sync-assignee serenakeyitan→ on-disk config.json hassyncMode: "open-issues"andsyncAssignee: "serenakeyitan"; daemon stops cleanly.Validation
pnpm typecheckclean.pnpm buildclean.pnpm vitest run tests/gardener/gardener-daemon.test.ts— 47/47 tests pass (up from 32).Follow-ups (not in this PR)
--sync-mode open-issuesas the autonomous-chain setup. Will land in a separate docs PR once this lands to keep the review surface tight.--sync-applyis removed in a future minor, also drop thesyncApply: booleanback-compat branch incoerceSyncMode.